package sifeap.pl.managedbean.usuarios;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import org.primefaces.model.DualListModel;

import sifeap.bl.ejb.usuarios.RolBLLocal;
import sifeap.bl.ejb.usuarios.UsuarioBLLocal;
import sifeap.entities.usuarios.Rol;
import sifeap.entities.usuarios.Usuario;
import sifeap.entities.usuarios.valueobject.UsuarioVO;
import sifeap.exception.SifeapException;
import sifeap.pl.util.FacesUtils;
import sifeap.wrappers.asociados.VinculadoWrapper;

@ManagedBean(name="usuariosManagedBean")
@SessionScoped
public class UsuariosManagedBean {
	private String documento;
	private String nombres;
	private String apellidos;
	private String contrasena;
	private String confirmContrasena;
	private Boolean habilitado;
	
	private String nombreUsuario; //Atributo usado para restaurar la contrasena
	
	private List<UsuarioVO> listaUsuarios;
	
	private DualListModel<Rol> roles;
	
	private int accion;
	
	private final String MENSAJES_BUNDLE = "sifeap.pl.bundles.mensajes";
	
	@EJB
	private UsuarioBLLocal usuarioBL;
	
	@EJB
	private RolBLLocal rolBL;
	
	@PostConstruct
	public void inicializar() {
		setHabilitado(true); //Ajusta por defecto
		buscarTodos();
		cargarRoles(null);
	}
	
	public String getDocumento() {
		return documento;
	}
	
	public void setDocumento(String documento) {
		this.documento = documento;
	}
	
	public String getNombres() {
		return nombres;
	}
	
	public void setNombres(String nombres) {
		this.nombres = nombres;
	}
	
	public String getApellidos() {
		return apellidos;
	}
	
	public void setApellidos(String apellidos) {
		this.apellidos = apellidos;
	}
	
	public String getContrasena() {
		return contrasena;
	}
	
	public void setContrasena(String contrasena) {
		this.contrasena = contrasena;
	}
	
	public String getConfirmContrasena() {
		return confirmContrasena;
	}
	
	public void setConfirmContrasena(String confirmContrasena) {
		this.confirmContrasena = confirmContrasena;
	}

	public Boolean getMostrarResultados() {
		if (listaUsuarios != null && listaUsuarios.size() > 0) {
			return true;
		} else {
			return false;
		}
	}

	public List<UsuarioVO> getListaUsuarios() {
		return listaUsuarios;
	}

	public void setListaUsuarios(List<UsuarioVO> listaUsuarios) {
		this.listaUsuarios = listaUsuarios;
	}
	
	public DualListModel<Rol> getRoles() {
		return roles;
	}

	public void setRoles(DualListModel<Rol> roles) {
		this.roles = roles;
	}

	public int getAccion() {
		return accion;
	}

	public void setAccion(int accion) {
		this.accion = accion;
	}

	public Boolean getHabilitado() {
		return habilitado;
	}

	public void setHabilitado(Boolean habilitado) {
		this.habilitado = habilitado;
	}

	public void buscarAsociado() {
		//Valido obligatorios...
		if (!validarObligatorios(true, false)) {
			return;
		}
		
		try {
			if (buscarAsociado(getDocumento(), true) == null) {
				return;
			}
		} catch (Exception e) {
			setNombres(null);
			setApellidos(null);
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.asociado.error"), false);
			} catch (SifeapException ex) {
				ex.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	private UsuarioVO buscarAsociado(String id, boolean verificarUsuario) {
		UsuarioVO usuario = null;
		try {
			usuario = usuarioBL.buscarPorId(getDocumento());
			
			if (usuario.getVinculado() == null) {
				//No existe el asociado...
				setNombres(null);
				setApellidos(null);
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.asociado.noexiste"), false);
				
				return null;
			} else if (verificarUsuario) {
				//El asociado si existe
				//Verifica si el usuario no existe
				Usuario usuarioConsultado = usuarioBL.buscar(getDocumento());
				if (usuarioConsultado != null && usuarioConsultado.getNombreUsuario() != null) {
					//El usuario Existe
					FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.usuarioExiste"), false);
				}
			}
			
			cargarDatosDocumento(usuario.getVinculado());
		} catch (SifeapException e) {
			e.printStackTrace();
		}
		return usuario;
	}
	
	public void guardar() {
		try {
			//Valido obligatorios...
			if (getAccion() == UsuarioVO.ACCION_MODIFICAR) {
				if (!validarObligatorios(false, true)) {
					return;
				}
			} else {
				if (!validarObligatorios(false, false)) {
					return;
				}
			}
			
			//Se asegura de que el asociado exista
			if (buscarAsociado(getDocumento(), false) == null) {
				return;
			}
			
			//Arma la entidad
			Usuario usuario;
			
			if (getAccion() == UsuarioVO.ACCION_MODIFICAR) {
				usuario = usuarioBL.buscar(getDocumento());
			} else {
				usuario = new Usuario();
				usuario.setNombreUsuario(getDocumento());
				usuario.setPassword(getContrasena());
				usuario.setRequierecambio("1"); //Por defecto requiere cambio de clave cuando se crea
			}
			
			usuario.setHabilitado(getHabilitado() ? "1" : "0");
			usuario.setRoles(getRoles().getTarget());
			
			//Arma el value object
			UsuarioVO usuarioVo = new UsuarioVO();
			usuarioVo.setConfirmarContrasena(getConfirmContrasena());
			usuarioVo.setUsuario(usuario);
			
			byte resultado = 0;
			
			if (getAccion() == UsuarioVO.ACCION_MODIFICAR) {
				if (usuarioBL.modificar(usuario)) {
					resultado = 1;
				} else {
					resultado = 0;
				}
			} else {
				resultado = usuarioBL.crear(usuarioVo);
			}
			
			//Evalua la respuesta de BL
			switch (resultado) {
			case 0:
				//Se produjo un error
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.crear.error"), false);
				break;
			case 1:
				//Se guardo correctamente
				buscarTodos();
				if (getAccion() == UsuarioVO.ACCION_MODIFICAR) {
					FacesUtils.addInfoMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.modificar.exito"), false);
				} else {
					FacesUtils.addInfoMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.crear.exito"), false);
				}
				
				limpiarCampos();
				break;
			case 2:
				//El usuario ya existe
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.usuarioExiste"), false);
				break;
			case 3:
				//La contrasenas no concuerdan
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.noconcuerda"), false);
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.crear.error"), false);
			} catch (SifeapException ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public String cancelar() {
		if(getAccion() == UsuarioVO.ACCION_MODIFICAR) {
			limpiarCampos();
		} else {
			setAccion(UsuarioVO.ACCION_CREAR);
		}
		return "/web/usuarios/usuarios.jsf?faces-redirect=true";
	}
	
	public String limpiar() {
		limpiarCampos();
		return "/web/usuarios/usuarios.jsf?faces-redirect=true";
	}
	
	public void cargarEditar() {		
		String idUsuario = FacesUtils.getRequestParameter("p_idusuario_edit");
		
		if (idUsuario != null) {
			setAccion(UsuarioVO.ACCION_MODIFICAR);
			
			try {
				UsuarioVO usuario = usuarioBL.buscarPorId(idUsuario);
				setDocumento(usuario.getUsuario().getNombreUsuario());
				cargarDatosDocumento(usuario.getVinculado());
				
				String estado = usuario.getUsuario().getHabilitado();
				setHabilitado(estado.equalsIgnoreCase("1") ? true : false);
				
				cargarRoles(usuario.getUsuario().getRoles());
			} catch (SifeapException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void cargarRestaurar() {
		nombreUsuario = FacesUtils.getRequestParameter("p_idusuario_rest");
	}
	
	public void restaurar() {
		try {
			boolean resultado = usuarioBL.restaurarUsuario(nombreUsuario);
			
			if (resultado) {
				FacesUtils.addInfoMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.restaurar.exito"), false);
				limpiarCampos();
			}
		} catch (SifeapException e) {
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.restaurar.error"), false);
			} catch (SifeapException e1) {}
			e.printStackTrace();
		}
	}
	
	/**
	 * Se implementan las validaciones de obligatoriedad a nivel de managedBean
	 * @param soloDocumento indiga si solamente se debe evaluar el documento
	 * @return <code>true</code> si las validaciones estan correctas
	 */
	private boolean validarObligatorios(boolean soloDocumento, boolean modificarUsuario) {
		boolean resultado = true;
		
		//Valida el documento
		if (!(getDocumento() != null && getDocumento().trim().length() > 0)) {
			resultado = false;
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.documento.obligatorio"), false);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		if (soloDocumento) {
			return resultado;
		}
		
		//Valida los nombres
		if (!(getNombres() != null && getNombres().trim().length() > 0)) {
			resultado = false;
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.nombres.obligatorio"), false);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		//Valida los nombres
		if (!(getApellidos() != null && getApellidos().trim().length() > 0)) {
			resultado = false;
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.apellidos.obligatorio"), false);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		
		if (!modificarUsuario) {
			//Valida los contrasena
			if (!(getContrasena() != null && getContrasena().trim().length() > 0)) {
				resultado = false;
				try {
					FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.contrasena.obligatorio"), false);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
			//Valida los contrasena
			if (!(getConfirmContrasena() != null && getConfirmContrasena().trim().length() > 0)) {
				resultado = false;
				try {
					FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.confirmcontrasena.obligatorio"), false);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		
		//Valida que se haya seleccionado por lo menos un rol
		List<Rol> rolesDestino = new ArrayList<Rol>();
		if (roles != null) {
			rolesDestino = roles.getTarget();
		}
		
		if (!(rolesDestino != null && rolesDestino.size() > 0)) {
			resultado = false;
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.usuarios.roles.obligatorio"), false);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return resultado;
	}
	
	private void buscarTodos() {
		try {
			listaUsuarios = usuarioBL.buscarTodosAsociados();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void cargarDatosDocumento(VinculadoWrapper vinculadoWp) {
		setNombres((vinculadoWp.getPrimerNombre() != null ? vinculadoWp.getPrimerNombre() : "") 
				+ (vinculadoWp.getSegundoNombre() != null ? " " + vinculadoWp.getSegundoNombre() : ""));
		setApellidos((vinculadoWp.getPrimerApellido() != null ? vinculadoWp.getPrimerApellido() : "") 
				+ (vinculadoWp.getSegundoApellido() != null ? " " + vinculadoWp.getSegundoApellido() : ""));
	}
	
	private void limpiarCampos() {
		setAccion(UsuarioVO.ACCION_CREAR);
		setDocumento("");
		setNombres(null);
		setApellidos(null);
		setContrasena(null);
		setConfirmContrasena(null);
		setHabilitado(true);
		cargarRoles(null); //Carga los roles
		nombreUsuario = null;
	}
	
	private void cargarRoles(List<Rol> rolesSeleccionados) {
		List<Rol> rolesOrigen = new ArrayList<Rol>();
		List<Rol> rolesDestino = new ArrayList<Rol>();
		
		try {
			rolesOrigen = rolBL.buscarTodos();
			if (rolesSeleccionados != null && rolesSeleccionados.size() > 0) {
				List<Rol> rolesRestantes = new ArrayList<Rol>(rolesOrigen);
				for (Rol rolSeleccionado : rolesSeleccionados) {
					for (Rol rolOrigen : rolesOrigen) {
						if (rolSeleccionado.getNombreRol().equals(rolOrigen.getNombreRol())) {
							//Este rol ya existe!
							rolesRestantes.remove(rolOrigen);
						}
					}
				}
				rolesOrigen = new ArrayList<Rol>(rolesRestantes);
				rolesDestino = new ArrayList<Rol>(rolesSeleccionados);
			}
		} catch (SifeapException e) {
			e.printStackTrace();
		}
			
		roles = new DualListModel<Rol>(rolesOrigen, rolesDestino);
	}
	
	/**
	 * Verifica si para el usuario autenticado tiene los permisos solicitados
	 * @return
	 */
	public boolean isTienePermisos() {
		return LoginManagedBean.tienePermisos("admon_usuarios:crear","admon_usuarios:editar","admon_usuarios:consultar");
	}
}